﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Universe.OneC.DomainModel;

namespace Universe.OneC
{
    public abstract class PropertyValue
    {
        public enum PropertyKind
        {
            Failed,
            Unknown,
            Primitive,
            EnumRef,
            CatalogRef,
            DocumentRef,
            CalculationRef,
            TablePart,
        }

        public virtual string Type1C { get; set; }
        public virtual bool HasValue { get; set; }
        public abstract PropertyKind Kind { get; }
        public abstract string ToDumpString();

        public abstract string TypeToDump();
        public abstract string ValueToDump();

    }

    public class FailedPropertyValue : PropertyValue
    {
        public override PropertyKind Kind
        {
            get { return PropertyKind.Failed; }
        }

        public override string ToDumpString()
        {
            return "[Fail]";
        }

        public override string TypeToDump()
        {
            return "[Fail]";
        }

        public override string ValueToDump()
        {
            return null;
        }
    }

    public class UnknownPropertyValue : PropertyValue
    {
        public override PropertyKind Kind
        {
            get { return PropertyKind.Unknown; }
        }

        public override string ToDumpString()
        {
            return "[Unknown" + (string.IsNullOrEmpty(Type1C) ? "" : " " + Type1C) + "]";
        }

        public override string TypeToDump()
        {
            return "[Unknown" + (string.IsNullOrEmpty(Type1C) ? "" : " " + Type1C) + "]";
        }

        public override string ValueToDump()
        {
            return null;
        }
    }

    public class PrimitivePropertyValue : PropertyValue
    {
        public PrimitivePropertyValue(object value)
        {
            Value = value;
        }

        public override PropertyKind Kind
        {
            get { return PropertyKind.Primitive; }
        }

        public object Value { get; set; }

        public override bool HasValue
        {
            get
            {
                return !(Value == null || Value == DBNull.Value);
            }
            set
            {
                base.HasValue = value;
                if (!base.HasValue)
                    Value = null;
            }
        }

        public override string ToDumpString()
        {
            return
                HasValue
                    ? "[" + Value.GetType().Name + "] " + Value
                    : "[Null]";
        }

        public override string TypeToDump()
        {
            return
                HasValue
                    ? "[" + Value.GetType().Name + "]"
                    : "[Null]";
        }

        public override string ValueToDump()
        {
            return HasValue
                ? Value.ToString()
                : null;
        }
    }

    public class PropertyOfEnumRef : PropertyValue
    {
        private int _index;
        private MetaEnumValue _MetaValue;

        public PropertyOfEnumRef(int index, MetaEnumValue metaValue)
        {
            _index = index;
            _MetaValue = metaValue;
        }

        public override PropertyKind Kind
        {
            get { return PropertyKind.EnumRef; }
        }

        public int Index
        {
            get { return _index; }
            set { _index = value; }
        }

        public MetaEnumValue MetaValue
        {
            get { return _MetaValue; }
            set { _MetaValue = value; }
        }

        public override string ToDumpString()
        {
            return 
                ("[" + Type1C + "] ")
                   + (!HasValue
                          ? "<<Empty>>"
                          : MetaValue.Value);

        }

        public override string TypeToDump()
        {
            return ("[" + Type1C + "]");
        }

        public override string ValueToDump()
        {
            return
                !HasValue
                     ? "<<Empty>>"
                     : MetaValue.Value;
        }
    }

    public class IdInstance
    {
        private object _value;

        public IdInstance(object value)
        {
            _value = value;
        }

        public object Value
        {
            get { return _value; }
            set
            {
                if (value is int || value is string || value == null || value == DBNull.Value)
                    _value = value == DBNull.Value ? null : value;

                else 
                    throw new ArgumentException("Type " + value.GetType() + " is not supported by id value");
            }
        }

        public bool HasValue
        {
            get { return Value != null; }
        }
    }

    public class PropertyOfCatalogRef : PropertyValue
    {
        public IdInstance Code { get; set; }
        
        // это дблирование. Все можно найти по коду
        public string Description { get; set; }
        public bool DeletionMark { get; set; }
        public bool Predefined { get; set; }
        public PropertyOfCatalogRef Parent { get; set; }
        public bool IsFolder { get; set; }
        public Guid Uid { get; set; }

        public override PropertyKind Kind
        {
            get { return PropertyKind.CatalogRef; }
        }

        public override string ToDumpString()
        {
            return
                ("[" + Type1C + "] ")
                   + (!(HasValue && Code.HasValue)
                          ? "<<Empty>>"
                          : Code.Value is string && ((string)Code.Value).Length == 0 ? Uid.ToString() : Code.Value);

        }

        public override string TypeToDump()
        {
            return ("[" + Type1C + "]");
        }

        public override string ValueToDump()
        {
            string ret =
                (!(HasValue && Code.HasValue)
                     ? "<<Empty>>"
                     : Code.Value is string && ((string) Code.Value).Length == 0
                           ? Uid.ToString()
                           : Code.Value == null ? "" : Code.Value.ToString());

            if (!string.IsNullOrEmpty(Description) && Description.Length > 0)
            {
                string d = Description.Length > 13 ? Description.Substring(0, 12) + "..." : Description;
                ret += " " + d;
            }

            return ret;
                
        }
    }

    public class PropertyOfDocumentRef : PropertyValue
    {
        public IdInstance Number { get; set; }
        public DateTime Date { get; set; }
        public bool DeletionMark { get; set; }
        public bool Posted { get; set; }
        public Guid Uid { get; set; }

        public override PropertyKind Kind
        {
            get { return PropertyKind.DocumentRef; }
        }

        public override string ToDumpString()
        {
            return
                ("[" + Type1C + "] ")
                   + (!HasValue
                          ? "<<Empty>>"
                          : Number.Value);
        }

        public override string TypeToDump()
        {
            return ("[" + Type1C + "]");
        }

        public override string ValueToDump()
        {
            return
                (!(HasValue && Number.HasValue)
                     ? "<<Empty>>"
                     : Number.Value is string && ((string)Number.Value).Length == 0 ? Uid.ToString() : Number.Value == null ? "" : Number.Value.ToString());
        }
    }

    public class PropertyOfCalculationRef : PropertyValue
    {
        public IdInstance Code { get; set; }
        public string Description { get; set; }
        public bool DeletionMark { get; set; }
        public bool Predefined { get; set; }
        public Guid Uid { get; set; }

        public override PropertyKind Kind
        {
            get { return PropertyKind.CatalogRef; }
        }

        public override string ToDumpString()
        {
            return
                ("[" + Type1C + "] ")
                   + (!(HasValue && Code.HasValue)
                          ? "<<Empty>>"
                          : Code.Value is string && ((string)Code.Value).Length == 0 ? Uid.ToString() : Code.Value);

        }

        public override string TypeToDump()
        {
            return ("[" + Type1C + "]");
        }

        public override string ValueToDump()
        {
            string ret =
                (!(HasValue && Code.HasValue)
                     ? "<<Empty>>"
                     : Code.Value is string && ((string)Code.Value).Length == 0
                           ? Uid.ToString()
                           : Code.Value == null ? "" : Code.Value.ToString());

            if (!string.IsNullOrEmpty(Description) && Description.Length > 0)
            {
                string d = Description.Length > 13 ? Description.Substring(0, 12) + "..." : Description;
                ret += " " + d;
            }

            return ret;

        }
    }

    public class PropertyOfTablePart : PropertyValue
    {
        public override PropertyKind Kind
        {
            get { return PropertyKind.TablePart; }
        }

        public List<RowOfTable1C> Rows = new List<RowOfTable1C>();

        public override string ToDumpString()
        {
            return 
                ("[" + Type1C + "] ")
                   + (!HasValue
                          ? "<<Empty>>"
                          : "<<" + Rows.Count + " rows" + ">>");

        }

        public override string TypeToDump()
        {
            return ("[" + Type1C + "]");
        }

        public override string ValueToDump()
        {
            return (!HasValue
                          ? "<<Empty>>"
                          : "<<" + Rows.Count + " rows" + ">>");
        }
    }

}
